package arcane.object.screen;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;

import org.lwjgl.opengl.GL11;

import arcane.constant.Constants;
import arcane.network.ArcaneClient;
import arcane.object.game.engine.ArcaneEngine;
import arcane.object.game.sprite.GeometricSprite;
import arcane.object.game.sprite.MenuSprite;
import arcane.object.gui.BevelBorder;
import arcane.object.gui.Border;
import arcane.object.gui.DefaultButton;
import arcane.object.gui.DefaultLabel;
import arcane.object.gui.FrameWork;
import arcane.object.gui.GTGETextField;
import arcane.object.gui.scroll.ScrollPanel;
import arcane.object.gui.specific.ArcaneKeyboardFilter;
import arcane.object.gui.specific.ArcaneKeyboardNumericFilter;
import arcane.object.gui.specific.PulsingPanel;

import com.golden.gamedev.GameEngine;
import com.golden.gamedev.GameObject;
import com.golden.gamedev.object.GameFont;

/**
 * Used to create initiate connection with some server/host on a network, and
 * log this player in on that server. Uses custom GUI components.
 * 
 * @author William Morrison
 * 
 */
public class MultiplayerLoginScreen extends GameObject implements
		ActionListener, Runnable {
	public ArcaneClient client;

	// Server detail GUI
	private DefaultLabel lblServerName;
	private DefaultLabel lblServerPort;
	private GTGETextField txtServerName;
	private GTGETextField txtServerPort;

	// Player's name GUI
	private DefaultLabel lblPlayerName;
	private DefaultLabel lblPlayerPass;
	private GTGETextField txtPlayerName;
	private GTGETextField txtPlayerPass;

	private DefaultButton btnOK;
	private DefaultButton btnCancel;

	private PulsingPanel pulsePanel;
	private DefaultLabel errorLabel;

	FrameWork frame;
	GeometricSprite earth;
	
	public MultiplayerLoginScreen(GameEngine engine) {
		super(engine);
	}

	public void initResources() {
		ArrayList<String> list = new ArrayList<String>(100);
		for(int i = 0;i<100;i++){
			list.add("Item"+i);
		}
		
		// upper left corner of server "panel"
		int x = 100;
		int y = 100;
		int vPad = 3;
		int hPad = 150;
		GameFont f = Constants.fontManager.getFont("MenuFont");
		int h = f.getHeight();
		int w = 240;
		Color color = Color.RED;

		earth = new GeometricSprite(Constants.getImage("Images/Menu/earth.png"));
		earth.setAngleIncrement(.02f);
		earth.setLocation(350, 220);

		errorLabel = new DefaultLabel("Welcome to multiplayer Arcane.");
		errorLabel.setLocation(40, 335);

		frame = new FrameWork(bsInput, 0, 0, 640, 475) {
			public void drawBackground(Graphics2D g, int x, int y) {
				GL11.glDisable(GL11.GL_TEXTURE_2D);

				GL11.glBegin(GL11.GL_QUADS);
				GL11.glColor4f(0f, 0f, 1f, 1f);
				GL11.glVertex2f(x, y);
				GL11.glVertex2f(x + width, y);

				GL11.glColor4f(0f, 0f, 0f, 0f);
				GL11.glVertex2f(x + width, y + height);
				GL11.glVertex2f(x, y + height);
				GL11.glEnd();
				GL11.glEnable(GL11.GL_TEXTURE_2D);
			}
		};
		frame.setColor(new Color(0f, 0f, 1f, .5f));

		// Server GUI fields
		lblServerName = new DefaultLabel("Host Name:", color, x, y);
		txtServerName = new GTGETextField(x + hPad, y, w, h + 3);
		lblServerPort = new DefaultLabel("Host Port:", color, x, y += h + vPad);
		txtServerPort = new GTGETextField(x + hPad, y, w, h + 3);
		txtServerPort.setMaxLength(5);
		txtServerPort.setKeyboardFilter(new ArcaneKeyboardNumericFilter());

		// Player GUI fields
		lblPlayerName = new DefaultLabel("User Name:", color, x, y += h + vPad);
		txtPlayerName = new GTGETextField(x + hPad, y, w, h + 3);
		txtPlayerName.setMaxLength(12);
		txtPlayerName.addActionListener(this);

		// no spaces, quotations, or colons
		txtPlayerName.setKeyboardFilter(new ArcaneKeyboardFilter(" \"\':"));

		lblPlayerPass = new DefaultLabel("User Pass:", color, x, y += h + vPad);
		txtPlayerPass = new GTGETextField(x + hPad, y, w, h + 3);
		txtPlayerPass.setMaxLength(20);
		txtPlayerPass.addActionListener(this);

		// no quotations
		txtPlayerPass.setKeyboardFilter(new ArcaneKeyboardFilter("\"\'"));

		Border border = new BevelBorder(BevelBorder.BEVEL_UP);
		btnOK = new DefaultButton("Ok");
		btnOK.setLocation(x + 110, y + 40);
		btnOK.setButtonBGColor(new Color(0f, 0f, 0f, .5f));
		btnOK.setBorder(border);
		btnCancel = new DefaultButton("Cancel");
		btnCancel.setLocation(x + 200, y + 40);
		btnCancel.setButtonBGColor(new Color(0f, 0f, 0f, .5f));
		btnCancel.setBorder(border);
		btnOK.addActionListener(this);
		btnCancel.addActionListener(this);

		frame.add(btnCancel);
		frame.add(btnOK);

		frame.add(lblServerName);
		frame.add(txtServerName);
		frame.add(lblServerPort);
		frame.add(txtServerPort);
		frame.add(lblPlayerName);
		frame.add(txtPlayerName);
		frame.add(lblPlayerPass);
		frame.add(txtPlayerPass);

		txtServerName.setText("localhost");// "orochi.ham.muohio.edu");
		txtServerPort.setText("4900");

		pulsePanel = new PulsingPanel();
		pulsePanel.setLocation(-320, 300);
		pulsePanel.setWidth(640);
		pulsePanel.setHeight(100);

		frame.setFocused(txtPlayerName);
	}

	public void render(Graphics2D g) {
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, 640, 480);
		frame.render(g);
		earth.render(g);
		g.setColor(new Color(0f, 0f, 0f, .7f));
		g.fillRect(5, 300, 640, 100);
		pulsePanel.render(g);
		errorLabel.render(g);
	}

	public void update(long time) {
		frame.update(time);
		earth.update(time);
		pulsePanel.update(time);
	}

	/**
	 * Runs an attempt to connect to server in a separate thread. This prevents
	 * the socket's creation from blocking the game's main thread.
	 */
	public void run() {
		String serverName = this.txtServerName.getText();
		String playerName = txtPlayerName.getText();
		if (playerName.length() == 0) {
			btnOK.setEnabled(true);
			frame.setFocused(txtPlayerName);
			errorLabel.setText("Missing player name.");
			return;
		} else if (serverName.length() == 0) {
			btnOK.setEnabled(true);
			frame.setFocused(txtServerName);
			errorLabel.setText("Missing server name or IP Address");
			return;
		}
		int portNum;
		try {
			portNum = Integer.parseInt(txtServerPort.getText());
			errorLabel.setText("Connecting to host \""
					+ txtServerName.getText() + "\"");
			client = new ArcaneClient(serverName, portNum);
			client.createOutputStream();
			client.createInputStream();
			btnOK.setEnabled(true);
		}
		// This should never execute thanks to numeric keyboard filter.
		catch (NumberFormatException e) {
			errorLabel.setText("Enter only numeric data for port number");
			btnOK.setEnabled(true);
			return;
		} catch (IOException e) {
			System.out.println(e);
			errorLabel.setText("Failed to connect to " + serverName);
			btnOK.setEnabled(true);
		}
		String playerPass = txtPlayerPass.getText();
		client.setDataID(playerName);

		synchronized (this) {
			parent.nextGameID = ArcaneEngine.MULTI_LONGE;
			finish();
		}
	}

	public void actionPerformed(ActionEvent e) {
		String s = e.getActionCommand();
		if (e.getSource() == txtPlayerName
				&& e.getID() == MenuSprite.UNSPECIFIED) {
			btnOK.setEnabled(false);
			new Thread(this).start();
		}
		if (e.getID() == MenuSprite.MOUSE_DOWN) {
			if (s.equals("Ok")) {
				btnOK.setEnabled(false);
				new Thread(this).start();
			} else if (s.equals("Cancel")) {
				this.parent.nextGameID = ArcaneEngine.MENU_SCREEN;
				this.finish();
			}
		}
	}
}